package api

import (
	"feishup2pclient/data"
	MSG "feishup2pclient/msg"
	"feishup2pclient/p2p"
	"feishup2pclient/wg"
	"fmt"
	"net"
	"net/http"
	"runtime"
	"sort"
	"strings"
	"sync/atomic"

	"github.com/DeanThompson/ginpprof"
	"github.com/gin-gonic/gin"
)

type RouteParam struct {
	Route string `json:"route"`
	Ip    string `json:"ip"`
}

var Flag int32

func InitApi() {
	if !atomic.CompareAndSwapInt32(&Flag, 0, 1) {
		return
	}

	r := gin.Default()
	r.GET("/p2p", getStatus)
	r.GET("/check", checkStatus)
	r.GET("/t", t)
	r.GET("/p2ptest/:id/:ip", func(c *gin.Context) {
		_ = p2p.SetRelayServer("QmbaLkSVNUhn8wHKsi8U1GPAisUBxhwDA69zD8kmpHeyoL", "")
		id := c.Param("id")
		ip := c.Param("ip")
		if err := p2p.Up(id, ip); err != nil {
			c.JSON(http.StatusOK, gin.H{"err": err.Error()})
			return
		}
		c.JSON(http.StatusOK, gin.H{"msg": "ok"})
	})
	r.POST("/route", func(c *gin.Context) {
		params := &RouteParam{}
		if err := c.ShouldBindJSON(params); err != nil {
			c.JSON(http.StatusOK, gin.H{"err": err.Error()})
			return
		}
		p2p.Routes[params.Route] = params.Ip
		c.JSON(http.StatusOK, gin.H{"msg": "ok"})
	})
	r.GET("/setRelayServer/:serverId", func(c *gin.Context) {
		id := c.Param("serverId")
		if err := p2p.SetRelayServer(id, "/ip4/115.227.19.84/tcp/8001"); err != nil {
			c.JSON(http.StatusOK, gin.H{"err": err.Error()})
			return
		}
		c.JSON(http.StatusOK, gin.H{"msg": "ok"})
	})
	l, err := net.Listen("tcp", ":9091")
	if err != nil {
		MSG.SendMessage(fmt.Sprintf("api 启动失败:%s", err.Error()))
		// log.Errorf("api 启动失败:%s", err.Error())
		return
	}
	ginpprof.Wrap(r)
	runtime.SetBlockProfileRate(1)
	runtime.SetMutexProfileFraction(1)
	data.ControlPort = l.Addr().(*net.TCPAddr).Port
	MSG.SendMessage(fmt.Sprintf("飞鼠客户端地址curl: curl localhost:%d/p2p | jq\n", data.ControlPort))
	fmt.Printf("飞鼠客户端地址curl: curl localhost:%d/p2p | jq\n", data.ControlPort)
	if err := r.RunListener(l); err != nil {
		// log.Errorf("api 启动失败:%s", err.Error())
	}

}

func getStatus(c *gin.Context) {
	list := make([]map[string]string, 0)
	self := make(map[string]string)
	self[`name`] = data.SelfClientName + "(本机)"
	self[`ip`] = strings.Split(data.SelfIp, `/`)[0]
	self[`OsName`] = data.SelfOsName
	list = append(list, self)
	data.LocalPeers.Range(func(key, value any) bool {
		localPeer := value.(*data.LocalPeer)
		result := make(map[string]string)
		result[`name`] = localPeer.Name
		result[`ip`] = localPeer.InnerIp
		result[`mode`] = localPeer.Mode
		result[`OsName`] = localPeer.OsName
		result[`configAddTime`] = localPeer.ConfigAddTime.Format("2006-01-02 15:04:05")
		if !localPeer.ConfigDelTime.IsZero() {
			result[`configDelTime`] = localPeer.ConfigDelTime.Format("2006-01-02 15:04:05")
		}
		if !localPeer.ConfigUpdateTime.IsZero() {
			result[`configUpdateTime`] = localPeer.ConfigUpdateTime.Format("2006-01-02 15:04:05")
		}
		result[`status`] = localPeer.StatusToStr()
		if localPeer.Status == 2 {
			rtt, err := wg.GetRtt(strings.Split(localPeer.InnerIp, ":")[0])
			if err != nil {
				result[`rtt`] = "未知"

			} else {
				result[`rtt`] = rtt
			}
		}
		list = append(list, result)
		return true
	})
	sort.Slice(list, func(i, j int) bool {
		return strings.Compare(list[i][`name`], list[j][`name`]) > 0
	})
	c.JSON(http.StatusOK, gin.H{"msg": "ok", "list": list})
}

func checkStatus(c *gin.Context) {
	wg := c.Request.Header.Get("wg")
	if wg == `wg` {
		// log.Infof("响应%s", strings.Split(data.SelfIp, "/")[0])
		MSG.SendMessage(fmt.Sprintf("响应%s", strings.Split(data.SelfIp, "/")[0]))
		c.Writer.WriteString(strings.Split(data.SelfIp, "/")[0])
	}
}

func t(c *gin.Context) {
	c.JSON(http.StatusOK, gin.H{"msg": "ok"})
}

func GetStatus() []map[string]string {
	list := make([]map[string]string, 0)
	self := make(map[string]string)
	self[`name`] = data.SelfClientName + "(本机)"
	self[`ip`] = strings.Split(data.SelfIp, `/`)[0]
	self[`OsName`] = data.SelfOsName
	list = append(list, self)
	data.LocalPeers.Range(func(key, value any) bool {
		localPeer := value.(*data.LocalPeer)
		result := make(map[string]string)
		result[`name`] = localPeer.Name
		result[`ip`] = localPeer.InnerIp
		result[`mode`] = localPeer.Mode
		result[`OsName`] = localPeer.OsName
		result[`configAddTime`] = localPeer.ConfigAddTime.Format("2006-01-02 15:04:05")
		if !localPeer.ConfigDelTime.IsZero() {
			result[`configDelTime`] = localPeer.ConfigDelTime.Format("2006-01-02 15:04:05")
		}
		if !localPeer.ConfigUpdateTime.IsZero() {
			result[`configUpdateTime`] = localPeer.ConfigUpdateTime.Format("2006-01-02 15:04:05")
		}
		result[`status`] = localPeer.StatusToStr()
		if localPeer.Status == 2 {
			rtt, err := wg.GetRtt(strings.Split(localPeer.InnerIp, ":")[0])
			if err != nil {
				result[`rtt`] = "未知"
			} else {
				result[`rtt`] = rtt
			}
		}
		list = append(list, result)
		return true
	})

	return list
}
